package me.edzh.spring.bootstrap.resolvers;

import lombok.extern.log4j.Log4j;
import me.edzh.spring.bootstrap.annotations.CurrentUser;
import me.edzh.spring.bootstrap.annotations.NeedAuth;
import me.edzh.spring.bootstrap.utils.Constants;
import me.edzh.spring.bootstrap.model.IUser;
import me.edzh.spring.bootstrap.utils.ResultCode;
import me.edzh.spring.bootstrap.utils.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 * Created by EdCho
 * 2018/4/7 007.
 */
@Log4j
public class CurrentUserResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        //如果参数类型是User并且有CurrentUser注解则支持
        if (IUser.class.isAssignableFrom(methodParameter.getParameterType()) &&
                methodParameter.hasParameterAnnotation(CurrentUser.class)) {

            return true;
        }


        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        String userId = (String)nativeWebRequest.getAttribute(Constants.KEY_REQUEST_USER_ID, RequestAttributes.SCOPE_REQUEST);
        if (userId == null)
            return null;


        if (userProvider == null){
            throw new RuntimeException("@CurrentUser can be available when a class implements CurrentUserResolver.UserProvider");
        }


        IUser user = userProvider.getUserOfId(userId);
        NeedAuth auth = methodParameter.getMethodAnnotation(NeedAuth.class);
        if (auth != null && user == null) { // 对登录态进行二次检查, 避免token中userId为不存在的值
            throw new ServiceException(ResultCode.ERROR_TOKEN_INVALID_CODE, "未登录");
        }

        return user;
    }

    @Autowired(required = false)
    private UserProvider userProvider;

    public interface UserProvider{
        IUser getUserOfId(String id);
    }
}
